
#include	"SysConfig.h"
#include	"Define.h"
#include	"Function.h"
#include	"Serial_Flash.h"
#include	"Utill.h"
#include	"PhoneBook.h"
#ifdef  BLUETOOTH
#include	"Bluetooth.h"
#endif

#ifdef  PHONE_BOOK

extern unsigned char ucBT_CallerID[BT_CALLERID_LEN];

#define	PBAP_BLOCK_DATA_SIZE	512
unsigned char 	ucPBAP_BlockDataBuf[PBAP_BLOCK_DATA_SIZE];
unsigned short	usPBAP_BlockDataBufCnt;
unsigned char ucPBAP_CurrentContents;

unsigned char ucPBAP_CharacterSet;
unsigned char ucPBAP_EncodeType;
#define	PBAP_ENC_QUOTED		1
#define	PBAP_ENC_NONE		0

PBAP_LIST	sPBAP_List;
#ifdef  PBAP_TEST_ROM
PBAP_LIST_TEST	sPBAP_ListRom[100];
unsigned char ucPBAP_ListRomCnt;
#endif
unsigned short usPBAP_ListCnt;
PBAP_LIST	sPBAP_CallHistory[PBAP_NUMBER_CALL_HISTORY];
unsigned char ucPBAP_CallHistoryCnt;

unsigned char ucPBAP_Mode;
#define	PBAP_MODE_IDLE			0
#define	PBAP_MODE_PARSING		1
#define	PBAP_MODE_SEARCH		2
#define	PBAP_MODE_SEARCH_END	3
#define	PBAP_MODE_WRITE_START	4
#define	PBAP_MODE_WRITE			5
#define	PBAP_MODE_CHECK_DEVICE_ADDR	6

unsigned short usPBAP_ListReadNum;

#ifdef  SERIAL_FLASH
extern unsigned char SF_WriteData_Start(unsigned long int uiAddrs);
extern unsigned char SF_TX_SetData(unsigned char ucData);
extern unsigned char SF_RequestWriteClose(void);
extern unsigned char SF_CommunicationActived(void);
extern unsigned char SF_CommunicationHold(void);
extern unsigned char SF_CommunicationWriteEnd(void);
extern unsigned char SF_GetReceiveDataNumber(void);
extern unsigned long int uiSF_WriteAddress;
extern unsigned char SF_Read_Start(unsigned long int uiAddr, unsigned char ucCnt);
#endif
extern BT_DEVICE	sBT_ConnectedDevice;

void PBAP_CallHistoryReset(void)
{
	ucPBAP_CallHistoryCnt = 0;
}

void PBAP_DataInit(void)
{
	usPBAP_ListCnt = 0;
#ifdef  SERIAL_FLASH
	uiSF_WriteAddress = SF_PHONEBOOK_ADDR;
#endif
}

void PBAP_SelectMode(unsigned char ucMode)
{
#ifdef  PBAP_TEST_ROM
	ucPBAP_ListRomCnt = 0;
#endif
	ucPBAP_CurrentContents = ucMode;// PBAP_CONTENTS_CALLHISTORY
}

/*////////////////////////////////////////////////////////////////////////
Title : unsigned char PB_SetData(unsigned char *ucBuf, unsigned char Cnt)
Return
-. 0 : Buffer Not ready
-. 1 : Buffer Full
-. 2 :
////////////////////////////////////////////////////////////////////////*/
unsigned char PBAP_MakeBlockData(unsigned char ucBuf)
{	
	ucPBAP_BlockDataBuf[usPBAP_BlockDataBufCnt] = ucBuf;
	++usPBAP_BlockDataBufCnt;
	
	if  (usPBAP_BlockDataBufCnt > 1)
	{
		if  ((ucPBAP_BlockDataBuf[usPBAP_BlockDataBufCnt] == 0x0A) && (ucPBAP_BlockDataBuf[usPBAP_BlockDataBufCnt - 1] == 0x0D))
		{
			return(1);
		}
	}
	if  (usPBAP_BlockDataBufCnt == PBAP_BLOCK_DATA_SIZE)
	{
		return(2);
	}
	return(0);
}


void PBAP_InitBlockData(void)
{
	memset(&ucPBAP_BlockDataBuf[0], 0x00, PBAP_BLOCK_DATA_SIZE);
	usPBAP_BlockDataBufCnt = 0;
}

unsigned short PBAP_GetBlockSize(unsigned char *ucData, unsigned short usSize)
{
	unsigned short i;

	for(i = 0; i < usSize; ++i)
	{
		if  ((*(ucData + i) == 0x0D) && (*(ucData + i + 1) == 0x0A))
		{
			return(i);
		}
		if  (i == PBAP_BLOCK_DATA_SIZE)
		{
			return(i);
		}
	}

	return(0xFFFF);
}

unsigned char PBAP_GetCharacterSetType(unsigned char *ucData, unsigned short usSize)
{
	unsigned short i;
	
	ucPBAP_CharacterSet = PBAP_CHAR_NONE;
	ucPBAP_EncodeType = PBAP_ENC_NONE;
	
	for(i = 0; i < usSize; ++i)
	{
		if  (*ucData == ':')
		{
			break;
		}
		if  (memcmp(ucData, "UTF-8", 5) == 0)
		{
			ucPBAP_CharacterSet = PBAP_CHAR_UTF8;
		}
		if  (memcmp(ucData, "QUOTED", 6) == 0)
		{
			ucPBAP_EncodeType = PBAP_ENC_QUOTED;
		}
		++ucData;
	}

	return(i + 1);
}


unsigned char PBAP_DecodeQuoted(unsigned char *ucData)
{
	unsigned char data_dec, tmp , i;

	data_dec = 0;
	for(i = 0 ; i < 2 ; i++)
	{
		if(*ucData >= '0' && *ucData <= '9')
		{
			tmp = *ucData - '0';
		}
		else if(*ucData >= 'A' && *ucData <= 'F')
		{
			tmp = *ucData - 'A' + 10;
		}
		else if(*ucData >= 'a' && *ucData <= 'f')
		{
			tmp = *ucData - 'a' + 10;
		}
		else
		{
			return 0xFF;
		}

		if(i == 0)
		{
			data_dec = tmp << 4;
		}
		else
		{
			data_dec += tmp;
		}
		++ucData;
	}

	return(data_dec);
}


unsigned short PBAP_GetNameData(unsigned char *ucData, unsigned char *ucBuf, unsigned short usSize)
{
	unsigned char i;
	unsigned char ucCnt = 0;
	
	if  (usSize == 0)
	{
		return(0);
	}
	
	if	(ucPBAP_EncodeType == PBAP_ENC_QUOTED)
	{
		for(i = 0; i < usSize; ++i)
		{
			if  (i > 126)
			{
				break;
			}
			if  (*(ucData + i) == ';')
			{
				break;
			}
			if  ((*(ucData + i) == 0x0D) && (*(ucData + i + 1) == 0x0A))
			{
				break;
			}
			
			if  (*(ucData + i) == '=')
			{
				*ucBuf = PBAP_DecodeQuoted(ucData + i + 1);
				if  (*ucBuf == 0xFF)
				{
					break;
				}
				++ucCnt;
				++ucBuf;
				i = i + 2;
			}

		}
	}
	else
	{
		for(i = 0; i < usSize; ++i)
		{
			if  (i > 126)
			{
				break;
			}
			*(ucBuf + i) = *(ucData + i);
		}
		ucCnt = i;
	}

	return(ucCnt);
}

unsigned char PBAP_NameDataToString(unsigned char *ucData, unsigned short usCnt)
{
	unsigned char *ucName;
	unsigned char i;

	if  (usCnt == 0)
	{
		return(0);
	}
	
	if  (ucPBAP_CurrentContents == PBAP_CONTENTS_CALLHISTORY)
	{
		ucName = &sPBAP_CallHistory[ucPBAP_CallHistoryCnt].ucName[0];
	}
	else
	{
		ucName = &sPBAP_List.ucName[0];
	}
	
	memset(ucName, 0x00,PBAP_NAME_BUFF_SIZE);
	
	if  (usCnt > PBAP_NAME_BUFF_SIZE)
	{
		usCnt = PBAP_NAME_BUFF_SIZE;
	}

	if  (ucPBAP_CharacterSet == PBAP_CHAR_UTF8)
	{
		UTILL_UTF8ToUnicode(ucData, ucName, usCnt, PBAP_NAME_BUFF_SIZE);
	}
	else
	{
		for(i = 0; i < usCnt; ++i)
		{
			*(ucName + i) = *(ucData + i);
		}
	}

	#ifdef  PBAP_TEST_ROM
		memset(&sPBAP_ListRom[ucPBAP_ListRomCnt].ucName[0], 0x00, PBAP_NAME_SIZE);
		memcpy(&sPBAP_ListRom[ucPBAP_ListRomCnt].ucName[0], &sPBAP_List.ucName[0], PBAP_NAME_SIZE);			
	#endif
	return(1);
}

unsigned char PBAP_SkipToName(unsigned char *ucData, unsigned char usSize)
{
	unsigned short i;

	for(i = 0; i < usSize; ++i)
	{
		if  (*(ucData + i) == ';')
		{
			break;
		}
	}

	return(i + 1);
}

void PBAP_SaveName(unsigned char *ucData, unsigned short usSize)
{
	unsigned short usNum;
	unsigned char ucNameTemp[128];
	unsigned short usNameTempCnt;

	usNum = PBAP_GetCharacterSetType(ucData, usSize);
	ucData = ucData + usNum;
	usSize = usSize - usNum;
//	usNum = PBAP_SkipToName(ucData, usSize);
//	ucData = ucData + usNum;
//	usSize = usSize - usNum;

	memset(&ucNameTemp[0], 0x00, 128);
	usNameTempCnt = PBAP_GetNameData(ucData, &ucNameTemp[0], usSize);

	PBAP_NameDataToString(&ucNameTemp[0], usNameTempCnt);
	sPBAP_List.ucCharSet = ucPBAP_CharacterSet;
}

#define PBAP_NUM_TYPE_OTHER 	0
#define PBAP_NUM_TYPE_CELL		1
#define PBAP_NUM_TYPE_HOME		2
#define PBAP_NUM_TYPE_WORK		3

void PBAP_memcpy(unsigned char *ucBuf, unsigned char *ucData, unsigned char ucCnt)
{
	unsigned char i;

	for(i = 0; i < ucCnt; ++i)
	{
		if  (*ucData != '-')
		{
			*ucBuf = *ucData;
			++ucBuf;
		}
		++ucData;
	}
}

void PBAP_SaveTelNumber(unsigned char *ucData, unsigned short usSize)
{
	unsigned char ucTelNumType;	
	unsigned char i;
	unsigned char *Number;

	ucTelNumType = PBAP_NUM_TYPE_OTHER;

	for(i = 0; i < usSize; ++i)
	{
		if  (*(ucData + i) == ':')
		{
			ucData = ucData + i + 1;
			usSize = usSize - (i + 1);
			break;
		}
		if  (memcmp(&ucData[i], "CELL", 4) == 0)
		{
			ucTelNumType = PBAP_NUM_TYPE_CELL;
		}
		else  if  (memcmp(&ucData[i], "HOME", 4) == 0)
		{
			ucTelNumType = PBAP_NUM_TYPE_HOME;
		}
		else  if  (memcmp(&ucData[i], "WORK", 4) == 0)
		{
			ucTelNumType = PBAP_NUM_TYPE_WORK;
		}
	}

	
	if  (ucPBAP_CurrentContents == PBAP_CONTENTS_CALLHISTORY)
	{
		if  (ucPBAP_CallHistoryCnt >= PBAP_NUMBER_CALL_HISTORY)
		{
			return;
		}
	}
	if  (usSize > PBAP_NUMBER_BUFF_SIZE)
	{
		usSize = PBAP_NUMBER_BUFF_SIZE;
	}
	switch  (ucTelNumType)
	{
		case PBAP_NUM_TYPE_CELL:
			if  (ucPBAP_CurrentContents == PBAP_CONTENTS_CALLHISTORY)
			{
				Number = &sPBAP_CallHistory[ucPBAP_CallHistoryCnt].ucCell[0];
			}
			else
			{
				Number = &sPBAP_List.ucCell[0];
			}
			memset(Number, 0x00, PBAP_NUMBER_BUFF_SIZE);
			PBAP_memcpy(Number, ucData, usSize);
		#ifdef  PBAP_TEST_ROM
			if  (ucPBAP_CurrentContents == PBAP_CONTENTS_PHONEBOOK)
			{
				memset(&sPBAP_ListRom[ucPBAP_ListRomCnt].ucPhone[0], 0x00, PBAP_NUMBER_BUFF_SIZE);
				memcpy(&sPBAP_ListRom[ucPBAP_ListRomCnt].ucPhone[0], ucData, usSize);			
			}
		#endif
			break;
		case PBAP_NUM_TYPE_HOME:
			if  (ucPBAP_CurrentContents == PBAP_CONTENTS_CALLHISTORY)
			{
				Number = &sPBAP_CallHistory[ucPBAP_CallHistoryCnt].ucHome[0];
			}
			else
			{
				Number = &sPBAP_List.ucCell[0];
			}
			memset(Number, 0x00, PBAP_NUMBER_BUFF_SIZE);
			PBAP_memcpy(Number, ucData, usSize);
			break;
		case PBAP_NUM_TYPE_WORK:
			if  (ucPBAP_CurrentContents == PBAP_CONTENTS_CALLHISTORY)
			{
				Number = &sPBAP_CallHistory[ucPBAP_CallHistoryCnt].ucWork[0];
			}
			else
			{
				Number = &sPBAP_List.ucCell[0];
			}
			memset(Number, 0x00, PBAP_NUMBER_BUFF_SIZE);
			PBAP_memcpy(Number, ucData, usSize);
			break;
		case PBAP_NUM_TYPE_OTHER:
			if  (ucPBAP_CurrentContents == PBAP_CONTENTS_CALLHISTORY)
			{
				Number = &sPBAP_CallHistory[ucPBAP_CallHistoryCnt].ucOther[0];
			}
			else
			{
				Number = &sPBAP_List.ucCell[0];
			}
			memset(Number, 0x00, PBAP_NUMBER_BUFF_SIZE);
			PBAP_memcpy(Number, ucData, usSize);
			break;
	}
}

void PBAP_SavePhoneBook(unsigned char *ucData, unsigned short usSize)
{
	if  ((usSize > 1) && (memcmp(ucData, "N;", 2) == 0))
	{
//		PBAP_SaveName(ucData + 2, usSize - 2);
	}
	else  if  ((usSize > 2) && (memcmp(ucData, "FN;", 3) == 0))
	{
		PBAP_SaveName(ucData + 3, usSize - 3);
	}
	else  if  ((usSize > 3) && (memcmp(ucData, "TEL;", 4) == 0))
	{
		PBAP_SaveTelNumber(ucData + 4, usSize - 4);
	}
	else  if  ((usSize > 3) && (memcmp(ucData, "CELL:", 4) == 0))
	{
		PBAP_SaveTelNumber(ucData, usSize);
	}
	else  if  ((usSize > 3) && (memcmp(ucData, "HOME:", 4) == 0))
	{
		PBAP_SaveTelNumber(ucData, usSize);
	}
	else  if  ((usSize > 3) && (memcmp(ucData, "WORK:", 4) == 0))
	{
		PBAP_SaveTelNumber(ucData, usSize);
	}
	else  if  ((usSize > 2) && (memcmp(ucData, "END", 3) == 0))
	{
		if  (ucPBAP_CurrentContents == PBAP_CONTENTS_CALLHISTORY)
		{
			++ucPBAP_CallHistoryCnt;
			if  (ucPBAP_CallHistoryCnt > PBAP_NUMBER_CALL_HISTORY)
			{
				ucPBAP_CallHistoryCnt = PBAP_NUMBER_CALL_HISTORY;
			}
		}
		else
		{
			unsigned char *ucData;
			unsigned char i;

			if  (usPBAP_ListCnt < PBAP_NUMBER)
			{
				LOG_BT("<< PB Save:%d >>", usPBAP_ListCnt);

				sPBAP_List.usNumber = usPBAP_ListCnt;
				ucData = &sPBAP_List.ucName[0];
				for(i = 0; i < sizeof(PBAP_LIST); ++i)
				{
			#ifdef  SERIAL_FLASH
					SF_TX_SetData(*ucData);
			#endif
					++ucData;
				}
				++usPBAP_ListCnt;				
		#ifdef  PBAP_TEST_ROM
				if  (++ucPBAP_ListRomCnt > 99)
				{
					ucPBAP_ListRomCnt = 99;
				}
		#endif
			}
		}
	}
}

unsigned char PBAP_VcardParsing(unsigned char *ucData, unsigned short usSize)
{
	unsigned short i, BlockSize;

	for(i = 0; i < usSize; ++i)
	{
		if	(ucPBAP_CurrentContents == PBAP_CONTENTS_CALLHISTORY)
		{
			if  (ucPBAP_CallHistoryCnt == PBAP_NUMBER_CALL_HISTORY)
			{
				return(0);
			}
		}
		else
		{
			if  (usPBAP_ListCnt == PBAP_NUMBER)
			{
				return(0);
			}
		}
		
		BlockSize = PBAP_GetBlockSize(ucData + i, usSize - i);	// with One-Line complete
		
		if  (BlockSize == 0xFFFF)
		{
			return(usSize - i);
		}
		if  (ucPBAP_CurrentContents == PBAP_CONTENTS_PHONEBOOK)
		{
			PBAP_SavePhoneBook(ucData + i, BlockSize);
		}
		if  (ucPBAP_CurrentContents == PBAP_CONTENTS_CALLHISTORY)
		{
			PBAP_SavePhoneBook(ucData + i, BlockSize);
		}
	}
	
	return(usSize - i);
}

unsigned char PBAP_Parsing(void)
{
	unsigned char ucRet;
	
	ucRet = PBAP_VcardParsing(&ucPBAP_BlockDataBuf[0],usPBAP_BlockDataBufCnt);

	return(ucRet);
}

unsigned char ucPBAP_SearchResult;

void PBAP_CompareCallerID(void)
{
	if  ((strlen(&sPBAP_List.ucHome[0]) != 0) && (memcmp(&sPBAP_List.ucHome[0], &ucBT_CallerID[0], PBAP_NUMBER_BUFF_SIZE) == 0))
	{
		ucPBAP_SearchResult = 1;
	}
	if  ((strlen(&sPBAP_List.ucWork[0]) != 0) && (memcmp(&sPBAP_List.ucWork[0], &ucBT_CallerID[0], PBAP_NUMBER_BUFF_SIZE) == 0))
	{
		ucPBAP_SearchResult = 1;
	}
	if  ((strlen(&sPBAP_List.ucCell[0]) != 0) && (memcmp(&sPBAP_List.ucCell[0], &ucBT_CallerID[0], PBAP_NUMBER_BUFF_SIZE) == 0))
	{
		ucPBAP_SearchResult = 1;
	}
	if  ((strlen(&sPBAP_List.ucOther[0]) != 0) && (memcmp(&sPBAP_List.ucOther[0], &ucBT_CallerID[0], PBAP_NUMBER_BUFF_SIZE) == 0))
	{
		ucPBAP_SearchResult = 1;
	}
}

void PBAP_SearchStart(void)
{
	if  (ucPBAP_Mode != PBAP_MODE_IDLE)
	{
		return;
	}

	LOG_PBAP("PBAP_SearchStart");
	ucPBAP_SearchResult = 0;
	usPBAP_ListReadNum = 0;
	ucPBAP_Mode = PBAP_MODE_CHECK_DEVICE_ADDR;

	memset(&sPBAP_List.ucName[0], 0x00, sizeof(PBAP_LIST));
}

void PBAP_Main(void)
{
	unsigned char *ucData;
	unsigned char i;
	
	switch  (ucPBAP_Mode)
	{
		case PBAP_MODE_IDLE:
		#if 0
			if  (FUNC_GetCurrentFunction() == FUNC_HF)
			{
				if  (strlen(&ucBT_CallerID[0]) != 0)
				{
					ucPBAP_SearchResult = 0;
					usPBAP_ListReadNum = 0;
					ucPBAP_Mode = PBAP_MODE_CHECK_DEVICE_ADDR;

					memset(&sPBAP_List.ucName[0], 0x00, sizeof(PBAP_LIST));
				}
			}
		#endif	
			break;
		case PBAP_MODE_CHECK_DEVICE_ADDR:
		#ifdef  SERIAL_FLASH
			SF_Read_Start(SF_BT_DEVICE_ADDR, 6);
			LOG_PBAP("PBAP ADDRESS");
			while(1)
			{
				if  (SF_GetReceiveDataNumber() == 0)
				{
					break;
				}
			}
			SF_Read_End();

			{
				unsigned char ucData[6];
				for(i = 0; i < 6; ++i)
				{
					ucData[i] = SF_RX_GetData();
					LOG_PBAP("%X", ucData[i]);
				}
				if  (memcmp(&ucData[0], &sBT_ConnectedDevice.ucDeviceAdr[0], 6) == 0)
				{
					ucPBAP_Mode = PBAP_MODE_SEARCH;
					LOG_PBAP("PBAP ADDRESS:OK");
				}
				else
				{
					ucPBAP_Mode = PBAP_MODE_SEARCH_END;
					LOG_PBAP("PBAP ADDRESS:NG");
				}
			}
		#endif
			break;
		case PBAP_MODE_SEARCH:
			#if 1
			if  (FUNC_GetCurrentFunction()!= FUNC_HF)
			{
				ucPBAP_Mode = PBAP_MODE_IDLE;
				return;
			}
			#endif
		#ifdef  SERIAL_FLASH
			SF_Read_Start(SF_PHONEBOOK_ADDR + usPBAP_ListReadNum * sizeof(sPBAP_List), sizeof(sPBAP_List));
			LOG_PBAP("PBAP Read");

			while(1)
			{
				if  (SF_GetReceiveDataNumber() == 0)
				{
					break;
				}
			}
			SF_Read_End();
			
			ucData = &sPBAP_List.ucName[0];
			for(i = 0; i < sizeof(sPBAP_List); ++i)
			{
				*ucData = SF_RX_GetData();
				++ucData;
			}
		#endif
			LOG_PBAP("PBAP Search Num:%d",sPBAP_List.usNumber);
			if  (sPBAP_List.usNumber > PBAP_NUMBER)
			{
				ucPBAP_Mode = PBAP_MODE_SEARCH_END;
				LOG_PBAP("PBAP Search:END");
			}
			else
			{
				PBAP_CompareCallerID();

				if  (ucPBAP_SearchResult == 1)
				{
					ucPBAP_Mode = PBAP_MODE_SEARCH_END;
					LOG_PBAP("PBAP Search:FIND");
				}
				++usPBAP_ListReadNum;
			}
			break;
		case PBAP_MODE_SEARCH_END:
			if  (FUNC_GetCurrentFunction() != FUNC_HF)
			{
				ucPBAP_Mode = PBAP_MODE_IDLE;
				ucPBAP_SearchResult = 0;
				usPBAP_ListReadNum = 0;
				LOG_PBAP("PBAP:END");
			}
			break;
	}
}

#endif

